<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>轻奢客餐厅3D效果图配置器</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r154/three.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/dat-gui/0.7.9/dat.gui.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
            background: #f5f5f5;
            overflow: hidden;
        }
        
        #canvas-container {
            position: relative;
            width: 100vw;
            height: 100vh;
        }
        
        #controls {
            position: absolute;
            top: 20px;
            left: 20px;
            background: rgba(255, 255, 255, 0.95);
            padding: 20px;
            border-radius: 12px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
            backdrop-filter: blur(10px);
            max-width: 300px;
        }
        
        .control-group {
            margin-bottom: 15px;
        }
        
        .control-group label {
            display: block;
            margin-bottom: 5px;
            font-size: 14px;
            color: #333;
            font-weight: 500;
        }
        
        .control-group input[type="range"] {
            width: 100%;
            margin-bottom: 5px;
        }
        
        .control-group input[type="color"] {
            width: 100%;
            height: 35px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
        }
        
        .btn {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            transition: all 0.3s ease;
            width: 100%;
            margin-top: 10px;
        }
        
        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
        }
        
        .info {
            position: absolute;
            bottom: 20px;
            right: 20px;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 15px;
            border-radius: 8px;
            font-size: 12px;
            max-width: 250px;
        }
        
        .loading {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 18px;
            color: #667eea;
        }
    </style>
</head>
<body>
    <div id="canvas-container">
        <div class="loading" id="loading">正在加载场景...</div>
    </div>
    
    <div id="controls">
        <h3 style="margin-bottom: 15px; color: #333;">轻奢客餐厅配置器</h3>
        
        <div class="control-group">
            <label>餐边柜宽度 (mm)</label>
            <input type="range" id="cabinetWidth" min="800" max="2400" value="1800" step="50">
            <span id="widthValue">1800</span>
        </div>
        
        <div class="control-group">
            <label>餐边柜高度 (mm)</label>
            <input type="range" id="cabinetHeight" min="600" max="1000" value="850" step="10">
            <span id="heightValue">850</span>
        </div>
        
        <div class="control-group">
            <label>餐边柜深度 (mm)</label>
            <input type="range" id="cabinetDepth" min="400" max="600" value="450" step="10">
            <span id="depthValue">450</span>
        </div>
        
        <div class="control-group">
            <label>冰箱位置</label>
            <input type="range" id="fridgePosition" min="0" max="100" value="50" step="1">
            <span id="positionValue">居中</span>
        </div>
        
        <div class="control-group">
            <label>餐边柜颜色</label>
            <input type="color" id="cabinetColor" value="#8B4513">
        </div>
        
        <div class="control-group">
            <label>台面材质</label>
            <select id="countertopMaterial" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;">
                <option value="marble">大理石</option>
                <option value="quartz">石英石</option>
                <option value="wood">实木</option>
            </select>
        </div>
        
        <button class="btn" onclick="exportImage()">导出高清效果图</button>
        <button class="btn" onclick="resetView()">重置视角</button>
    </div>
    
    <div class="info">
        <strong>操作提示：</strong><br>
        • 鼠标左键拖拽旋转视角<br>
        • 鼠标右键拖拽平移<br>
        • 滚轮缩放<br>
        • 使用左侧控制面板调整参数
    </div>

    <script>
        let scene, camera, renderer, controls;
        let cabinet, fridge, countertop;
        let cabinetGroup;
        
        // 轻奢材质库
        const luxuryMaterials = {
            marble: {
                color: 0xf8f8ff,
                roughness: 0.1,
                metalness: 0.1,
                clearcoat: 1.0,
                clearcoatRoughness: 0.1
            },
            quartz: {
                color: 0xe8e8e8,
                roughness: 0.05,
                metalness: 0.2,
                clearcoat: 1.0,
                clearcoatRoughness: 0.05
            },
            wood: {
                color: 0x8B4513,
                roughness: 0.4,
                metalness: 0.0,
                clearcoat: 0.3,
                clearcoatRoughness: 0.3
            }
        };
        
        function init() {
            // 创建场景
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0xf5f5f5);
            
            // 创建相机
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(5, 3, 5);
            
            // 创建渲染器
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMap.enabled = true;
            renderer.shadowMap.type = THREE.PCFSoftShadowMap;
            document.getElementById('canvas-container').appendChild(renderer.domElement);
            
            // 添加控制器
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
            controls.dampingFactor = 0.05;
            
            // 添加灯光
            setupLighting();
            
            // 创建场景内容
            createRoom();
            createCabinet();
            
            // 隐藏加载提示
            document.getElementById('loading').style.display = 'none';
            
            // 添加事件监听
            setupEventListeners();
            
            // 开始渲染循环
            animate();
        }
        
        function setupLighting() {
            // 环境光
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
            scene.add(ambientLight);
            
            // 主光源
            const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
            directionalLight.position.set(5, 10, 5);
            directionalLight.castShadow = true;
            directionalLight.shadow.camera.near = 0.1;
            directionalLight.shadow.camera.far = 50;
            directionalLight.shadow.camera.left = -10;
            directionalLight.shadow.camera.right = 10;
            directionalLight.shadow.camera.top = 10;
            directionalLight.shadow.camera.bottom = -10;
            directionalLight.shadow.mapSize.width = 2048;
            directionalLight.shadow.mapSize.height = 2048;
            scene.add(directionalLight);
            
            // 补光
            const fillLight = new THREE.DirectionalLight(0xffffff, 0.3);
            fillLight.position.set(-5, 5, -5);
            scene.add(fillLight);
        }
        
        function createRoom() {
            // 地板
            const floorGeometry = new THREE.PlaneGeometry(10, 10);
            const floorMaterial = new THREE.MeshLambertMaterial({ 
                color: 0xf0f0f0,
                transparent: true,
                opacity: 0.8
            });
            const floor = new THREE.Mesh(floorGeometry, floorMaterial);
            floor.rotation.x = -Math.PI / 2;
            floor.receiveShadow = true;
            scene.add(floor);
            
            // 墙壁
            const wallMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
            
            // 后墙
            const backWallGeometry = new THREE.PlaneGeometry(10, 4);
            const backWall = new THREE.Mesh(backWallGeometry, wallMaterial);
            backWall.position.set(0, 2, -5);
            scene.add(backWall);
            
            // 左墙
            const leftWallGeometry = new THREE.PlaneGeometry(10, 4);
            const leftWall = new THREE.Mesh(leftWallGeometry, wallMaterial);
            leftWall.position.set(-5, 2, 0);
            leftWall.rotation.y = Math.PI / 2;
            scene.add(leftWall);
        }
        
        function createCabinet() {
            cabinetGroup = new THREE.Group();
            
            // 餐边柜
            updateCabinet();
            
            scene.add(cabinetGroup);
        }
        
        function updateCabinet() {
            // 清除旧的模型
            while(cabinetGroup.children.length > 0) {
                cabinetGroup.remove(cabinetGroup.children[0]);
            }
            
            const width = document.getElementById('cabinetWidth').value / 1000;
            const height = document.getElementById('cabinetHeight').value / 1000;
            const depth = document.getElementById('cabinetDepth').value / 1000;
            const color = document.getElementById('cabinetColor').value;
            const materialType = document.getElementById('countertopMaterial').value;
            const fridgePosPercent = document.getElementById('fridgePosition').value / 100;
            
            // 餐边柜主体
            const cabinetGeometry = new THREE.BoxGeometry(width, height, depth);
            const cabinetMaterial = new THREE.MeshPhysicalMaterial({
                color: new THREE.Color(color),
                roughness: 0.3,
                metalness: 0.1,
                clearcoat: 0.5,
                clearcoatRoughness: 0.2
            });
            cabinet = new THREE.Mesh(cabinetGeometry, cabinetMaterial);
            cabinet.position.set(0, height/2, 0);
            cabinet.castShadow = true;
            cabinet.receiveShadow = true;
            cabinetGroup.add(cabinet);
            
            // 台面
            const countertopGeometry = new THREE.BoxGeometry(width + 0.02, 0.02, depth + 0.02);
            const countertopMaterial = new THREE.MeshPhysicalMaterial(luxuryMaterials[materialType]);
            countertop = new THREE.Mesh(countertopGeometry, countertopMaterial);
            countertop.position.set(0, height + 0.01, 0);
            countertop.castShadow = true;
            cabinetGroup.add(countertop);
            
            // 冰箱
            const fridgeWidth = 0.6;
            const fridgeHeight = 1.8;
            const fridgeDepth = 0.65;
            
            const fridgeGeometry = new THREE.BoxGeometry(fridgeWidth, fridgeHeight, fridgeDepth);
            const fridgeMaterial = new THREE.MeshPhysicalMaterial({
                color: 0x2c3e50,
                roughness: 0.1,
                metalness: 0.8,
                clearcoat: 1.0,
                clearcoatRoughness: 0.1
            });
            fridge = new THREE.Mesh(fridgeGeometry, fridgeMaterial);
            
            // 计算冰箱位置
            const fridgeX = -width/2 + fridgeWidth/2 + fridgePosPercent * (width - fridgeWidth);
            fridge.position.set(fridgeX, fridgeHeight/2, -depth/2 - fridgeDepth/2 + 0.1);
            fridge.castShadow = true;
            fridge.receiveShadow = true;
            cabinetGroup.add(fridge);
            
            // 添加把手
            const handleGeometry = new THREE.CylinderGeometry(0.01, 0.01, 0.8);
            const handleMaterial = new THREE.MeshPhysicalMaterial({
                color: 0xc0c0c0,
                roughness: 0.1,
                metalness: 0.9
            });
            const handle = new THREE.Mesh(handleGeometry, handleMaterial);
            handle.rotation.z = Math.PI / 2;
            handle.position.set(fridgeX + fridgeWidth/2 + 0.02, fridgeHeight/2, -depth/2 - fridgeDepth/2 + 0.1);
            cabinetGroup.add(handle);
        }
        
        function setupEventListeners() {
            // 尺寸控制
            document.getElementById('cabinetWidth').addEventListener('input', function(e) {
                document.getElementById('widthValue').textContent = e.target.value;
                updateCabinet();
            });
            
            document.getElementById('cabinetHeight').addEventListener('input', function(e) {
                document.getElementById('heightValue').textContent = e.target.value;
                updateCabinet();
            });
            
            document.getElementById('cabinetDepth').addEventListener('input', function(e) {
                document.getElementById('depthValue').textContent = e.target.value;
                updateCabinet();
            });
            
            document.getElementById('fridgePosition').addEventListener('input', function(e) {
                const value = e.target.value;
                let positionText = '居中';
                if (value < 20) positionText = '最左';
                else if (value > 80) positionText = '最右';
                else if (value < 40) positionText = '偏左';
                else if (value > 60) positionText = '偏右';
                document.getElementById('positionValue').textContent = positionText;
                updateCabinet();
            });
            
            document.getElementById('cabinetColor').addEventListener('input', updateCabinet);
            document.getElementById('countertopMaterial').addEventListener('change', updateCabinet);
            
            // 窗口大小调整
            window.addEventListener('resize', onWindowResize);
        }
        
        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }
        
        function animate() {
            requestAnimationFrame(animate);
            controls.update();
            renderer.render(scene, camera);
        }
        
        function exportImage() {
            renderer.setSize(1920, 1080);
            camera.aspect = 1920 / 1080;
            camera.updateProjectionMatrix();
            
            renderer.render(scene, camera);
            
            renderer.domElement.toBlob(function(blob) {
                const url = URL.createObjectURL(blob);
                const link = document.createElement('a');
                link.href = url;
                link.download = '轻奢客餐厅效果图.png';
                link.click();
                URL.revokeObjectURL(url);
                
                // 恢复原始尺寸
                renderer.setSize(window.innerWidth, window.innerHeight);
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
            });
        }
        
        function resetView() {
            camera.position.set(5, 3, 5);
            controls.reset();
        }
        
        // 添加OrbitControls
        THREE.OrbitControls = function(object, domElement) {
            this.object = object;
            this.domElement = domElement;
            this.enabled = true;
            this.target = new THREE.Vector3();
            this.enableDamping = false;
            this.dampingFactor = 0.05;
            
            const scope = this;
            const rotateSpeed = 0.005;
            const panSpeed = 0.01;
            const zoomSpeed = 0.02;
            
            let rotateStart = new THREE.Vector2();
            let rotateEnd = new THREE.Vector2();
            let rotateDelta = new THREE.Vector2();
            
            let panStart = new THREE.Vector2();
            let panEnd = new THREE.Vector2();
            let panDelta = new THREE.Vector2();
            
            let spherical = new THREE.Spherical();
            let sphericalDelta = new THREE.Spherical();
            
            let scale = 1;
            let panOffset = new THREE.Vector3();
            
            let mouseButtons = {
                LEFT: 0,
                MIDDLE: 1,
                RIGHT: 2
            };
            
            function onMouseDown(event) {
                if (!scope.enabled) return;
                
                event.preventDefault();
                
                if (event.button === mouseButtons.LEFT) {
                    rotateStart.set(event.clientX, event.clientY);
                    document.addEventListener('mousemove', onMouseMoveRotate);
                    document.addEventListener('mouseup', onMouseUpRotate);
                } else if (event.button === mouseButtons.RIGHT) {
                    panStart.set(event.clientX, event.clientY);
                    document.addEventListener('mousemove', onMouseMovePan);
                    document.addEventListener('mouseup', onMouseUpPan);
                }
            }
            
            function onMouseMoveRotate(event) {
                rotateEnd.set(event.clientX, event.clientY);
                rotateDelta.subVectors(rotateEnd, rotateStart);
                
                sphericalDelta.theta -= 2 * Math.PI * rotateDelta.x / scope.domElement.clientWidth * rotateSpeed;
                sphericalDelta.phi -= 2 * Math.PI * rotateDelta.y / scope.domElement.clientHeight * rotateSpeed;
                
                rotateStart.copy(rotateEnd);
                update();
            }
            
            function onMouseMovePan(event) {
                panEnd.set(event.clientX, event.clientY);
                panDelta.subVectors(panEnd, panStart);
                
                const offset = new THREE.Vector3();
                offset.set(panDelta.x * panSpeed, -panDelta.y * panSpeed, 0);
                offset.applyQuaternion(scope.object.quaternion);
                
                panOffset.add(offset);
                panStart.copy(panEnd);
                update();
            }
            
            function onMouseUpRotate() {
                document.removeEventListener('mousemove', onMouseMoveRotate);
                document.removeEventListener('mouseup', onMouseUpRotate);
            }
            
            function onMouseUpPan() {
                document.removeEventListener('mousemove', onMouseMovePan);
                document.removeEventListener('mouseup', onMouseUpPan);
            }
            
            function onWheel(event) {
                if (!scope.enabled) return;
                
                event.preventDefault();
                
                scale *= 1 - event.deltaY * zoomSpeed;
                scale = Math.max(0.1, Math.min(5, scale));
                
                update();
            }
            
            function update() {
                const offset = new THREE.Vector3();
                offset.copy(scope.object.position).sub(scope.target);
                
                spherical.setFromVector3(offset);
                spherical.theta += sphericalDelta.theta;
                spherical.phi += sphericalDelta.phi;
                spherical.phi = Math.max(0.1, Math.min(Math.PI - 0.1, spherical.phi));
                
                spherical.radius *= scale;
                spherical.radius = Math.max(2, Math.min(20, spherical.radius));
                
                offset.setFromSpherical(spherical);
                offset.add(panOffset);
                
                scope.object.position.copy(scope.target).add(offset);
                scope.object.lookAt(scope.target);
                
                sphericalDelta.set(0, 0, 0);
                panOffset.set(0, 0, 0);
                scale = 1;
            }
            
            this.reset = function() {
                scope.object.position.set(5, 3, 5);
                scope.target.set(0, 0, 0);
                scope.object.lookAt(scope.target);
            };
            
            this.update = update;
            
            scope.domElement.addEventListener('mousedown', onMouseDown);
            scope.domElement.addEventListener('wheel', onWheel);
            scope.domElement.addEventListener('contextmenu', event => event.preventDefault());
        };
        
        // 初始化场景
        init();
    </script>
</body>
</html>
